Chart
Allow users to view and interact with graphical representations of data.
#Intro
The Chart component is a tailored wrapper built for the Highcharts library within a React environment. It's designed to offer a seamless integration of Highcharts while incorporating customized features, improved accessibility, and enhanced usability.
#Key Features
- Customizations: The
Chartcomponent provides predefined customizations regarding colors, sizes, and themes to maintain consistency and visual appeal across charts. - Accessibility Improvements: Accessibility is a prime focus. The component ensures that charts are optimized for screen readers and other assistive technologies, making data visualization more inclusive.
- Enhanced Usability: With improved interaction elements and intuitive functionalities, the
Chartcomponent aims to enhance user experience and ease of navigation within the charts. - Highcharts Features: Developers have full access to all Highcharts features, allowing them to leverage the extensive capabilities of Highcharts to create sophisticated and detailed charts.
#Support and Troubleshooting
The Chart component strives to ensure a seamless experience with Highcharts integrations. If you encounter any issues or discrepancies specific to the Chart component that differ from the standard Highcharts behavior, please reach out to us for support. If the issue works as expected with Highcharts in its raw form, kindly let us know to address the compatibility concern.
#Examples
The examples below showcase the various kinds of charts suported by Highcharts, such as line charts, column charts, and more (coming soon). Click on the tabs to view the examples.
For general features and functionalities, please refer to the Miscellaneous section.
#Basic usage
<Chart
options={{
series: [
{
type: "line",
name: "Series 1",
data: [25, 23, 48, 52, 52, 57, 56, 61, 66].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
customValue: "customValue1",
};
}),
},
{
type: "line",
name: "Series 2",
data: [18, 26, 36, 44, 49, 59, 65, 71, 82].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
customValue: "customValue2",
};
}),
},
],
}}
/>#Usage with categories
<Chart
options={{
xAxis: {
categories: ["Apples", "Bananas", "Oranges", "Strawberries"],
tickInterval: 1,
},
series: [
{
type: "line",
name: "Series 1",
data: [25, 23, 48, 52],
},
{
type: "line",
name: "Series 2",
data: [18, 26, 36, 44],
},
],
}}
/>#Usage with X axis showing time
<Chart
options={{
xAxis: {
type: "datetime",
// Set interval of tick marks to one month. For datetime axes this is based on milliseconds.
tickInterval: 24 * 3600 * 1000 * 30,
},
series: [
{
type: "line",
name: "Series 1",
dashStyle: "ShortDot",
data: [
{
x: Date.UTC(2010, 0, 1),
y: 10,
},
{
x: Date.UTC(2010, 1, 2),
y: 20,
},
{
x: Date.UTC(2010, 2, 3),
y: 30,
},
{
x: Date.UTC(2010, 3, 4),
y: 40,
},
{
x: Date.UTC(2010, 4, 5),
y: 50,
},
],
},
{
type: "line",
name: "Series 2",
data: [
{
x: Date.UTC(2010, 0, 1),
y: 20,
},
{
x: Date.UTC(2010, 1, 2),
y: 30,
},
{
x: Date.UTC(2010, 2, 3),
y: 40,
},
{
x: Date.UTC(2010, 3, 4),
y: 50,
},
{
x: Date.UTC(2010, 5, 5),
y: 60,
},
],
},
],
}}
/>#Usage with multiple Y axes
<Chart
options={{
xAxis: [
{
type: "datetime",
// Set interval of tick marks to one month. For datetime axes this is based on milliseconds.
tickInterval: 24 * 3600 * 1000 * 30,
},
],
yAxis: [{}, { opposite: true }],
series: [
{
type: "line",
name: "Series 1",
data: [
{
x: Date.UTC(2010, 0, 1),
y: 10,
},
{
x: Date.UTC(2010, 1, 1),
y: 20,
},
{
x: Date.UTC(2010, 2, 1),
y: 30,
},
{
x: Date.UTC(2010, 3, 1),
y: 40,
},
{
x: Date.UTC(2010, 4, 1),
y: 50,
},
],
},
{
type: "line",
name: "Series 2",
data: [
{
x: Date.UTC(2010, 0, 1),
y: 20,
},
{
x: Date.UTC(2010, 1, 1),
y: 30,
},
{
x: Date.UTC(2010, 2, 1),
y: 40,
},
{
x: Date.UTC(2010, 3, 1),
y: 50,
},
{
x: Date.UTC(2010, 5, 1),
y: 60,
},
],
},
{
type: "line",
name: "Series 3",
data: [
{
x: Date.UTC(2010, 0, 1),
y: 25,
},
{
x: Date.UTC(2010, 1, 1),
y: 50,
},
{
x: Date.UTC(2010, 2, 1),
y: 75,
},
{
x: Date.UTC(2010, 3, 1),
y: 90,
},
{
x: Date.UTC(2010, 5, 1),
y: 105,
},
],
yAxis: 1,
},
],
}}
/>#Usage with several series
<Chart
options={{
series: [
{
type: "line",
name: "Series 1",
data: [1.12, 1.14, 1.13, 1.16, 1.18, 1.17, 1.15, 1.19, 1.2, 1.22].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
{
type: "line",
name: "Series 2",
data: [1.01, 1.05, 1.1, 1.09, 1.05, 1.02, 1.0, 1.01, 1.01, 1.02].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
{
type: "line",
name: "Series 3",
data: [0.9, 1.01, 1.02, 1.03, 1.02, 1.0, 0.98, 0.96, 0.95, 0.99].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
{
type: "line",
name: "Series 4",
data: [1.5, 1.6, 1.65, 1.7, 1.75, 1.78, 1.78, 1.79, 1.8, 1.8].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
{
type: "line",
name: "Series 5",
data: [1.4, 1.38, 1.35, 1.31, 1.3, 1.3, 1.29, 1.28, 1.3, 1.32].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
{
type: "line",
name: "Series 6",
data: [1.0, 1.1, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
],
}}
/>#Usage with Annotations
Annotations are designed to be easily adaptable to any backend. For that, you can map your own data structure to our Annotations interface which has the following definition:
type AnnotationItem = {
id: string | number;
date: Date;
category?: string;
comment: string;
createdBy: string;
visibility: string;
isFavorite: boolean;
visibleIn: string[];
username: string;
}In addition, the Chart component also provides properties for handling all basic annotation operations, such as creation (onCreateAnnotation), update (onUpdateAnnotation), and deletion (onDeleteAnnotation).
In the example below, the API object simulates the implementation of these methods and also provides a list of annotations according to the AnnotationItem interface.
const chartDateOptions: DateOptions = {
locale: "en-us",
skipTimezoneReset: false,
};
const [annotationsData, setAnnotationsData] = useState<AnnotationItem[]>([]);
const [annotationsAreasVisibleIn, setAnnotationsAreasVisibleIn] = useState<
AnnotationAreasVisibleIn[]
>([]);
useEffect(() => {
let isDataFetchDone = true;
API.fetch().then((data) => isDataFetchDone && setAnnotationsData(data));
API.fetchAreasVisibleIn().then(
(areas) => isDataFetchDone && setAnnotationsAreasVisibleIn(areas)
);
return () => {
isDataFetchDone = false;
};
}, []);
return (
<Chart
options={{
xAxis: {
type: "datetime",
// Set interval of tick marks to one month. For datetime axes this is based on milliseconds.
tickInterval: 24 * 3600 * 1000 * 30,
},
series: [
{
type: "line",
name: "Series 1",
data: [
{
x: Date.UTC(2022, 1, 1),
y: 20,
},
{
x: Date.UTC(2022, 2, 1),
y: 30,
},
{
x: Date.UTC(2022, 3, 1),
y: 40,
},
{
x: Date.UTC(2022, 4, 1),
y: 50,
},
{
x: Date.UTC(2022, 5, 1),
y: 30,
},
],
},
{
type: "line",
name: "Series 2",
data: [
{
x: Date.UTC(2022, 0, 1),
y: 20,
},
{
x: Date.UTC(2022, 1, 1),
y: 30,
},
{
x: Date.UTC(2022, 2, 1),
y: 40,
},
{
x: Date.UTC(2022, 3, 1),
y: 50,
},
{
x: Date.UTC(2022, 5, 1),
y: 60,
},
],
},
],
}}
showAnnotationButton
annotations={annotationsData}
chartPeriod={[new Date(2022, 0, 1), new Date(2022, 3, 1)]}
onUpdateAnnotation={async (data: Omit<Partial<AnnotationItem>, "createdBy">) => {
await API.update(data);
setAnnotationsData(await API.fetch());
}}
onCreateAnnotation={async (data: Omit<AnnotationItem, "id" | "createdBy">) => {
await API.create(data);
setAnnotationsData(await API.fetch());
}}
onDeleteAnnotation={async (id: string | number) => {
await API.delete(id);
setAnnotationsData(await API.fetch());
}}
chartDateOptions={chartDateOptions}
annotationAreasVisibleIn={annotationsAreasVisibleIn}
annotationAreasVisibleInDefaultSelect={["accessibility", "ads"]}
/>
);
#Miscellaneous
These examples showcase the various features and functionalities of the Chart component that are not specific to any particular chart type. It includes features such as legends, tooltips, sizes, and more.
#Usage with reference lines
const { ColorRed, ColorTextStaticBody } = useDesignToken();
return (
<Chart
options={{
yAxis: {
plotLines: [
{
value: 70,
color: ColorRed,
width: 3,
dashStyle: "ShortDot",
label: {
text: "Limit (70)",
align: "right",
x: -5,
style: {
color: ColorTextStaticBody,
},
},
},
],
},
series: [
{
type: "line",
name: "Series 1",
data: [25, 23, 48, 52, 52, 57, 56, 61, 66].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
{
type: "line",
name: "Series 2",
data: [15, 13, 38, 42, 42, 47, 46, 51, 56].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
],
}}
/>
);#Usage with no legend
<Chart
options={{
plotOptions: {
series: {
showInLegend: false,
},
},
series: [
{
type: "column",
name: "Series 1",
data: [25, 23, 48, 52, 52, 57, 56, 61, 66].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
customValue: "customValue1",
};
}),
},
{
type: "line",
name: "Series 2",
data: [18, 26, 36, 44, 49, 59, 65, 71, 82].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
customValue: "customValue2",
};
}),
},
],
}}
/>#Usage with series hidden on load
<Chart
options={{
series: [
{
type: "column",
name: "Series 1",
data: [25, 23, 48, 52, 52, 57, 56, 61, 66].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
{
type: "line",
name: "Series 2",
data: [18, 26, 36, 44, 49, 59, 65, 71, 82].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
selected: false,
},
],
}}
/>#Usage with series not visible in the legends
<Chart
options={{
series: [
{
type: "column",
name: "Series 1",
data: [25, 23, 48, 52, 52, 57, 56, 61, 66].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
{
showInLegend: false,
type: "line",
name: "Series 2",
data: [18, 26, 36, 44, 49, 59, 65, 71, 82].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
};
}),
},
],
}}
/>#Usage with missing data
If all series contain empty data (undefined, null or NaN) in a determined position, the row will not be displayed on the table visualization.
<Chart
options={{
series: [
{
type: "column",
name: "Series 1",
data: [25, 23, 48, 52, undefined, 52, 57, 56, 61].map((val, i) => {
return {
x: i,
y: val,
};
}),
},
{
type: "line",
name: "Series 2",
data: [18, 26, 36, 44, undefined, 49, 59, 65, 71].map((val, i) => {
return {
x: i,
y: val,
};
}),
},
],
}}
/>#Usage with tooltip formatters
The header of the chart tooltip can be formatted using the optional property tooltipHeaderFormatter with the values default, named, and keyed.
The individual points of the chart tooltip can be formatted using the optional property tooltipPointFormatter with the values default, named, and customValue.
<Chart
options={{
series: [
{
type: "column",
name: "Series 1",
data: [25, 23, 48, 52, 52, 57, 56, 61, 66].map((val, i) => {
return {
x: i,
y: val,
name: "Name for x: " + i.toString(),
customValue: "Custom value for x: " + i.toString() + " in series 1",
};
}),
},
{
type: "line",
name: "Series 2",
data: [18, 26, 36, 44, 49, 59, 65, 71, 82].map((val, i) => {
return {
x: i,
y: val,
name: "Name for x: " + i.toString(),
customValue: "Custom value for x: " + i.toString() + " in series 2",
};
}),
},
],
}}
tooltipHeaderFormatter="named"
tooltipPointFormatter="customValue"
/>#Visual
#Height
Use the height property to adjust the chart size. The default height is medium (310px) and should be used in most cases. Use small height when space is limited. Use large or a custom value when the previous sizes are not suitable.
function BaseChart(props: { height: ChartProps["height"] }) {
return (
<>
<InlineText emphasis="medium">{props.height}</InlineText>
<br />
<Chart
height={props.height}
hideContextMenu
options={{
series: [
{
type: "line",
name: "Series 1",
data: [25, 23, 48, 52, 52, 57, 56, 61, 66].map((val, i) => {
return {
x: i,
y: val,
name: val.toString(),
};
}),
},
],
}}
/>
</>
);
}
return (
<>
<BaseChart height="small" />
<BaseChart height="medium" />
<BaseChart height="large" />
</>
);#Usage with context menu changes
Use the hideContextMenu property to remove the Context Menu gear icon. The default setting is to show the Context Menu. In addition, use the hideEnhancedContrastOption property to remove the Enhanced contrast option from the Conext menu when that is visible. The default setting is to show the Enhanced Contrast option.
In the example below, the hideContextMenu is disabled and the hideEnhancedContrastOption is enabled.
<Chart
hideContextMenu={false}
hideEnhancedContrastOption
options={{
series: [
{
type: "column",
name: "Series 1",
data: [25, 23, 48, 52, 52, 57, 56, 61, 66].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
customValue: "customValue1",
};
}),
},
{
type: "line",
name: "Series 2",
data: [18, 26, 36, 44, 49, 59, 65, 71, 82].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
customValue: "customValue2",
};
}),
},
],
}}
/>#Usage with persistent legend state
Use the onToggleSeries property to persist the legend state. The default setting is to not persist the legend state, which means that the legend state will be reset when the page is refreshed. The visibility state of each series is controlled by the visible property of the series object.
const [series, setSeries] = useState<Highcharts.SeriesOptionsType[]>([
{
type: "column",
name: "Series 1",
visible: true,
data: [25, 23, 48, 52, 52, 57, 56, 61, 66].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
customValue: "customValue1",
};
}),
},
{
type: "line",
name: "Series 2",
visible: false,
data: [18, 26, 36, 44, 49, 59, 65, 71, 82].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
customValue: "customValue2",
};
}),
},
]);
return (
<Chart
onToggleSeries={(seriesIndex, visible) => {
const newSeries = [...series];
newSeries[seriesIndex].visible = visible;
setSeries(newSeries);
console.log(
"Save series visibility to user preferences (e.g.: localStorage)",
seriesIndex,
visible
);
}}
options={{ series }}
/>
);#Data updates
The Chart component automatically updates the chart when the options or height properties change. This is useful when the chart data is updated dynamically or the layout changes and the chart needs to be redrawn.
const numberOfSeries = 2;
const seriesLength = 10;
const buildData = () => generateRandomData(numberOfSeries, seriesLength);
const [series, setSeries] = useState<number[][]>(buildData());
return (
<Content>
<Button onClick={() => setSeries(buildData())}>Generate series</Button>
<Chart
options={{
series: [
{
type: "column",
name: "Series 1",
data: series[0].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
customValue: "customValue1",
};
}),
},
{
type: "line",
name: "Series 2",
data: series[1].map((val, i) => {
return {
x: i,
y: val,
name: i.toString(),
customValue: "customValue2",
};
}),
},
],
}}
/>
</Content>
);#Usage with no data
In some real-world scenarios, the chart may not have any data to display. In this case, the chart frame and the table view will be empty.
<Chart
options={{
series: [],
}}
/>#Properties
| Property | Description | Defined | Value |
|---|---|---|---|
optionsRequired | objectOptions for Highcharts chart | ||
showAnnotationButtonOptional | booleanShould show annotation button | ||
annotationsOptional | object[]Annotations array | ||
chartPeriodOptional | date[]Chart Period (for Annotations) | ||
onUpdateAnnotationOptional | functionPUT call to update Annotation | ||
onCreateAnnotationOptional | functionCREATE new Annotation | ||
onDeleteAnnotationOptional | functionDELETE new Annotation | ||
chartDateOptionsOptional | objectDate Options for the chart annotations | ||
annotationAreasVisibleInOptional | object[]Array of areas to allow annotations to be visible in | ||
heightOptional | | string | numberChart height (default medium, i.e. 310px) | ||
containerClassNameOptional | stringCSS class for the Highcharts wrapper | ||
useHighchartsLegendOptional | booleanUse native Highcharts legend | ||
screenReaderRegionLabelOptional | stringLabel for screen reader region | ||
screenReaderChartHeadingOptional | stringLabel for chart | ||
defaultChartTitleOptional | stringDefault chart label | ||
tableSummaryOptional | stringSummary for the data displayed in the data table | ||
chartContainerLabelOptional | stringLabel for chart container | ||
legendItemOptional | stringLegend item label | ||
onToggleSeriesOptional | functionCallback for toggling series visibility | ||
chartTypesMapTypeDescriptionOptional | stringDescription for chart type map type | ||
chartTypesCombinationChartOptional | stringDescription for chart type combination chart | ||
chartTypesDefaultSingleOptional | stringDescription for chart type default single | ||
chartTypesDefaultMultipleOptional | stringDescription for chart type default multiple | ||
chartTypesSplineSingleOptional | stringDescription for chart type spline single | ||
chartTypesSplineMultipleOptional | stringDescription for chart type spline multiple | ||
chartTypesLineSingleOptional | stringDescription for chart type line single | ||
chartTypesLineMultipleOptional | stringDescription for chart type line multiple | ||
chartTypesColumnSingleOptional | stringDescription for chart type column single | ||
chartTypesColumnMultipleOptional | stringDescription for chart type column multiple | ||
chartTypesBarSingleOptional | stringDescription for chart type bar single | ||
chartTypesBarMultipleOptional | stringDescription for chart type bar multiple | ||
chartTypesPieSingleOptional | stringDescription for chart type pie single | ||
chartTypesPieMultipleOptional | stringDescription for chart type pie multiple | ||
xAxisDescriptionSingularOptional | stringDescription for x-axis singluar | ||
xAxisDescriptionPluralOptional | stringDescription for x-axis plural | ||
categoryColumnHeaderOptional | stringTable column header for x-axis when the type is "category", "linear", or "logarithmic" | ||
datetimeColumnHeaderOptional | stringTable column header for x-axis when the type is "datetime" | ||
yAxisDescriptionSingularOptional | stringDescription for y-axis singluar | ||
yAxisDescriptionPluralOptional | stringDescription for y-axis plural | ||
chartSeriesDefaultOptional | stringChart series summary default | ||
chartSeriesDefaultCombinationOptional | stringChart series summary default combination | ||
chartSeriesLineOptional | stringChart series summary line | ||
chartSeriesLineCombinationOptional | stringChart series summary line combination | ||
chartSeriesSplineOptional | stringChart series summary spline | ||
chartSeriesSplineCombinationOptional | stringChart series summary spline combination | ||
chartSeriesColumnOptional | stringChart series summary column | ||
chartSeriesColumnCombinationOptional | stringChart series summary column combination | ||
chartSeriesBarOptional | stringChart series summary bar | ||
chartSeriesBarCombinationOptional | stringChart series summary bar combination | ||
chartSeriesPieOptional | stringChart series summary pie | ||
chartSeriesScatterCombinationOptional | stringChart series summary pie combination | ||
chartSeriesMapCombinationOptional | stringChart series summary map combination | ||
chartSeriesMapbubbleCombinationOptional | stringChart series summary mapbubble combination | ||
xAxisDescriptionOptional | stringDescription of x-axis | ||
yAxisDescriptionOptional | stringDescription of y-axis | ||
contextMenuForLabelOptional | stringLabel for the context menu. It will be appended with the chart title. | ||
contextMenuEnhancedContrastLabelOptional | stringLabel for the enhanced contrast button in the context menu | ||
contextMenuEnhancedContrastTooltipOptional | stringTooltip content for the enhanced contrast button | ||
contextMenuTableViewLabelOptional | stringLabel for table view button in the context menu | ||
contextMenuTableViewTooltipOptional | stringTooltip content for the table view button | ||
hideContextMenuOptional | booleanHides the context menu icon | ||
hideEnhancedContrastOptionOptional | booleanHides the enhanced contrast context option | ||
overflowableOptional | booleanShould overflow be allowed (if not, tooltip might be cut off) | ||
a11yModeOptional | booleanEnables enhanced contrast mode | ||
tooltipHeaderFormatterOptional | "default" | "keyed" | "named"Tooltip header formatters | ||
tooltipPointFormatterOptional | "customValue" | "default" | "named"Tooltip point formatters | ||
data-observe-keyOptional | stringUnique string, used by external script e.g. for event tracking | ||
classNameOptional | stringCustom className that's applied to the outermost element (only intended for special cases) | ||
styleOptional | objectStyle object to apply custom inline styles (only intended for special cases) |
#Guidelines
#Best practices
#Do not use when
#Accessibility
Explore detailed guidelines for this component: Accessibility Specifications